/*
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "animation/rs_animation_group.h"

#include "animation/rs_animation_callback.h"
#include "platform/common/rs_log.h"
#include "ui/rs_node.h"

namespace Keels {
namespace Rosen {
void RSAnimationGroup::AddAnimation(const std::shared_ptr<RSAnimation>& animation)
{
    if (animation == nullptr) {
        ROSEN_LOGE("Failed to add animation, adding animation is null!");
        return;
    }

    if (IsStarted()) {
        ROSEN_LOGE("Failed to add animation, group animation has started!");
        return;
    }

    if (animation->IsStarted()) {
        ROSEN_LOGE("Failed to add animation, adding animation has started!");
        return;
    }

    auto iter = find(animations_.begin(), animations_.end(), animation);
    if (iter != animations_.end()) {
        ROSEN_LOGE("Failed to add animation, animation already exists!");
        return;
    }

    animations_.emplace_back(animation);
}

void RSAnimationGroup::RemoveAnimation(const std::shared_ptr<RSAnimation>& animation)
{
    if (animation == nullptr) {
        ROSEN_LOGE("Failed to remove animation, animation is null!");
        return;
    }

    if (IsStarted()) {
        ROSEN_LOGE("Failed to remove animation, group animation has started!");
        return;
    }

    if (animation->IsStarted()) {
        ROSEN_LOGE("Failed to remove animation, removing animation has started!");
        return;
    }

    auto iter = find(animations_.begin(), animations_.end(), animation);
    if (iter == animations_.end()) {
        ROSEN_LOGE("Failed to remove animation, animation not exists!");
        return;
    }

    animations_.erase(iter);
}

void RSAnimationGroup::OnStart()
{
    if (animations_.empty()) {
        ROSEN_LOGD("Failed to start animations, animations is empty!");
        return;
    }

    auto target = target_.lock();
    if (target == nullptr) {
        ROSEN_LOGE("Failed to start group animation, target is null!");
        return;
    }

    std::shared_ptr<AnimationFinishCallback> finishCallback =
        std::make_shared<AnimationFinishCallback>([weakTarget = target_, weakAnimation = weak_from_this()]() {
            auto target = weakTarget.lock();
            if (target == nullptr) {
                ROSEN_LOGE("Failed to finish group animation, target is null!");
                return;
            }

            auto animation = weakAnimation.lock();
            if (animation == nullptr) {
                ROSEN_LOGE("Failed to finish group animation, group animation is null!");
                return;
            }

            target->RemoveAnimation(animation);
        });

    for (auto& animation : animations_) {
        int duration = duration_ < animation->GetDuration() ? duration_ : animation->GetDuration();
        int startDelay = startDelay_ + animation->GetStartDelay();

        animation->SetDuration(duration);
        animation->SetStartDelay(startDelay);
        animation->SetFinishCallback(finishCallback);
        animation->Start(target);
    }
}

void RSAnimationGroup::OnPause()
{
    if (animations_.empty()) {
        ROSEN_LOGE("Failed to pause animation, group animation is empty!");
        return;
    }

    for (auto& animation : animations_) {
        animation->Pause();
    }
}

void RSAnimationGroup::OnResume()
{
    if (animations_.empty()) {
        ROSEN_LOGE("Failed to resume animation, group animation is empty!");
        return;
    }

    for (auto& animation : animations_) {
        animation->Resume();
    }
}

void RSAnimationGroup::OnFinish()
{
    if (animations_.empty()) {
        ROSEN_LOGE("Failed to finish animation, group animation is empty!");
        return;
    }

    for (auto& animation : animations_) {
        animation->Finish();
    }
}

void RSAnimationGroup::OnReverse()
{
    if (animations_.empty()) {
        ROSEN_LOGE("Failed to reverse animation, group animation is empty!");
        return;
    }

    for (auto& animation : animations_) {
        animation->Reverse();
    }
}

void RSAnimationGroup::OnSetFraction(float fraction)
{
    if (animations_.empty()) {
        ROSEN_LOGE("Failed to set fraction, group animation is empty!");
        return;
    }

    for (auto& animation : animations_) {
        animation->SetFraction(fraction);
    }
}

PropertyId RSAnimationGroup::GetPropertyId() const
{
    return 0;
}

const std::string RS_MODIFIER_TYPE_TO_STRING(const RSModifierType type)
{
    switch (type) {
        case RSModifierType::INVALID:
            return "Invalid";
        case RSModifierType::BOUNDS:
            return "Bounds";
        case RSModifierType::FRAME:
            return "Frame";
        case RSModifierType::POSITION_Z:
            return "PositionZ";
        case RSModifierType::PIVOT:
            return "Pivot";
        case RSModifierType::PIVOT_Z:
            return "PivotZ";
        case RSModifierType::QUATERNION:
            return "Quaternion";
        case RSModifierType::ROTATION:
            return "Rotation";
        case RSModifierType::ROTATION_X:
            return "RotationX";
        case RSModifierType::ROTATION_Y:
            return "RotationY";
        case RSModifierType::CAMERA_DISTANCE:
            return "CameraDistance";
        case RSModifierType::SCALE:
            return "Scale";
        case RSModifierType::SKEW:
            return "Skew";
        case RSModifierType::PERSP:
            return "Persp";
        case RSModifierType::TRANSLATE:
            return "Translate";
        case RSModifierType::TRANSLATE_Z:
            return "TranslateZ";
        case RSModifierType::SUBLAYER_TRANSFORM:
            return "SublayerTransform";
        case RSModifierType::CORNER_RADIUS:
            return "CornerRadius";
        case RSModifierType::ALPHA:
            return "Alpha";
        case RSModifierType::ALPHA_OFFSCREEN:
            return "AlphaOffscreen";
        case RSModifierType::FOREGROUND_COLOR:
            return "ForegroundColor";
        case RSModifierType::BACKGROUND_COLOR:
            return "BackgroundColor";
        case RSModifierType::BACKGROUND_SHADER:
            return "BackgroundShader";
        case RSModifierType::BG_IMAGE:
            return "BgImage";
        case RSModifierType::BG_IMAGE_INNER_RECT:
            return "BgImageInnerRect";
        case RSModifierType::BG_IMAGE_WIDTH:
            return "BgImageWidth";
        case RSModifierType::BG_IMAGE_HEIGHT:
            return "BgImageHeight";
        case RSModifierType::BG_IMAGE_POSITION_X:
            return "BgImagePositionX";
        case RSModifierType::BG_IMAGE_POSITION_Y:
            return "BgImagePositionY";
        case RSModifierType::SURFACE_BG_COLOR:
            return "SurfaceBgColor";
        case RSModifierType::BORDER_COLOR:
            return "BorderColor";
        case RSModifierType::BORDER_WIDTH:
            return "BorderWidth";
        case RSModifierType::BORDER_STYLE:
            return "BorderStyle";
        case RSModifierType::BORDER_DASH_WIDTH:
            return "BorderDashWidth";
        case RSModifierType::BORDER_DASH_GAP:
            return "BorderDashGap";
        case RSModifierType::FILTER:
            return "Filter";
        case RSModifierType::BACKGROUND_FILTER:
            return "BackgroundFilter";
        case RSModifierType::LINEAR_GRADIENT_BLUR_PARA:
            return "LinearGradientBlurPara";
        case RSModifierType::DYNAMIC_LIGHT_UP_RATE:
            return "DynamicLightUpRate";
        case RSModifierType::DYNAMIC_LIGHT_UP_DEGREE:
            return "DynamicLightUpDegree";
        case RSModifierType::FG_BRIGHTNESS_RATES:
            return "FgBrightnessRates";
        case RSModifierType::FG_BRIGHTNESS_SATURATION:
            return "FgBrightnessSaturation";
        case RSModifierType::FG_BRIGHTNESS_POSCOEFF:
            return "FgBrightnessPoscoeff";
        case RSModifierType::FG_BRIGHTNESS_NEGCOEFF:
            return "FgBrightnessNegcoeff";
        case RSModifierType::FG_BRIGHTNESS_FRACTION:
            return "FgBrightnessFraction";
        case RSModifierType::BG_BRIGHTNESS_RATES:
            return "BgBrightnessRates";
        case RSModifierType::BG_BRIGHTNESS_SATURATION:
            return "BgBrightnessSaturation";
        case RSModifierType::BG_BRIGHTNESS_POSCOEFF:
            return "BgBrightnessPoscoeff";
        case RSModifierType::BG_BRIGHTNESS_NEGCOEFF:
            return "BgBrightnessNegcoeff";
        case RSModifierType::BG_BRIGHTNESS_FRACTION:
            return "BgBrightnessFraction";
        case RSModifierType::FRAME_GRAVITY:
            return "FrameGravity";
        case RSModifierType::CLIP_RRECT:
            return "ClipRrect";
        case RSModifierType::CLIP_BOUNDS:
            return "ClipBounds";
        case RSModifierType::CLIP_TO_BOUNDS:
            return "ClipToBounds";
        case RSModifierType::CLIP_TO_FRAME:
            return "ClipToFrame";
        case RSModifierType::VISIBLE:
            return "Visible";
        case RSModifierType::SHADOW_COLOR:
            return "ShadowColor";
        case RSModifierType::SHADOW_OFFSET_X:
            return "ShadowOffsetX";
        case RSModifierType::SHADOW_OFFSET_Y:
            return "ShadowOffsetY";
        case RSModifierType::SHADOW_ALPHA:
            return "ShadowAlpha";
        case RSModifierType::SHADOW_ELEVATION:
            return "ShadowElevation";
        case RSModifierType::SHADOW_RADIUS:
            return "ShadowRadius";
        case RSModifierType::SHADOW_PATH:
            return "ShadowPath";
        case RSModifierType::SHADOW_MASK:
            return "ShadowMask";
        case RSModifierType::SHADOW_COLOR_STRATEGY:
            return "ShadowColorStrategy";
        case RSModifierType::MASK:
            return "Mask";
        case RSModifierType::SPHERIZE:
            return "Spherize";
        case RSModifierType::LIGHT_UP_EFFECT:
            return "LightUpEffect";
        case RSModifierType::PIXEL_STRETCH:
            return "PixelStretch";
        case RSModifierType::PIXEL_STRETCH_PERCENT:
            return "PixelStretchPercent";
        case RSModifierType::PIXEL_STRETCH_TILE_MODE:
            return "PixelStretchTileMode";
        case RSModifierType::USE_EFFECT:
            return "UseEffect";
        case RSModifierType::COLOR_BLEND_MODE:
            return "ColorBlendMode";
        case RSModifierType::COLOR_BLEND_APPLY_TYPE:
            return "ColorBlendApplyType";
        case RSModifierType::SANDBOX:
            return "Sandbox";
        case RSModifierType::GRAY_SCALE:
            return "GrayScale";
        case RSModifierType::BRIGHTNESS:
            return "Brightness";
        case RSModifierType::CONTRAST:
            return "Contrast";
        case RSModifierType::SATURATE:
            return "Saturate";
        case RSModifierType::SEPIA:
            return "Sepia";
        case RSModifierType::INVERT:
            return "Invert";
        case RSModifierType::AIINVERT:
            return "Aiinvert";
        case RSModifierType::SYSTEMBAREFFECT:
            return "Systembareffect";
        case RSModifierType::HUE_ROTATE:
            return "HueRotate";
        case RSModifierType::COLOR_BLEND:
            return "ColorBlend";
        case RSModifierType::PARTICLE:
            return "Particle";
        case RSModifierType::SHADOW_IS_FILLED:
            return "ShadowIsFilled";
        case RSModifierType::OUTLINE_COLOR:
            return "OutlineColor";
        case RSModifierType::OUTLINE_WIDTH:
            return "OutlineWidth";
        case RSModifierType::OUTLINE_STYLE:
            return "OutlineStyle";
        case RSModifierType::OUTLINE_DASH_WIDTH:
            return "OutlineDashWidth";
        case RSModifierType::OUTLINE_DASH_GAP:
            return "OutlineDashGap";
        case RSModifierType::OUTLINE_RADIUS:
            return "OutlineRadius";
        case RSModifierType::GREY_COEF:
            return "GreyCoef";
        case RSModifierType::LIGHT_INTENSITY:
            return "LightIntensity";
        case RSModifierType::LIGHT_COLOR:
            return "LightColor";
        case RSModifierType::LIGHT_POSITION:
            return "LightPosition";
        case RSModifierType::ILLUMINATED_BORDER_WIDTH:
            return "IlluminatedBorderWidth";
        case RSModifierType::ILLUMINATED_TYPE:
            return "IlluminatedType";
        case RSModifierType::BLOOM:
            return "Bloom";
        case RSModifierType::FOREGROUND_EFFECT_RADIUS:
            return "ForegroundEffectRadius";
        case RSModifierType::USE_SHADOW_BATCHING:
            return "UseShadowBatching";
        case RSModifierType::MOTION_BLUR_PARA:
            return "MotionBlurPara";
        case RSModifierType::PARTICLE_EMITTER_UPDATER:
            return "ParticleEmitterUpdater";
        case RSModifierType::PARTICLE_NOISE_FIELD:
            return "ParticleNoiseField";
        case RSModifierType::DYNAMIC_DIM_DEGREE:
            return "DynamicDimDegree";
        case RSModifierType::MAGNIFIER_PARA:
            return "MagnifierPara";
        case RSModifierType::BACKGROUND_BLUR_RADIUS:
            return "BackgroundBlurRadius";
        case RSModifierType::BACKGROUND_BLUR_SATURATION:
            return "BackgroundBlurSaturation";
        case RSModifierType::BACKGROUND_BLUR_BRIGHTNESS:
            return "BackgroundBlurBrightness";
        case RSModifierType::BACKGROUND_BLUR_MASK_COLOR:
            return "BackgroundBlurMaskColor";
        case RSModifierType::BACKGROUND_BLUR_COLOR_MODE:
            return "BackgroundBlurColorMode";
        case RSModifierType::BACKGROUND_BLUR_RADIUS_X:
            return "BackgroundBlurRadiusX";
        case RSModifierType::BACKGROUND_BLUR_RADIUS_Y:
            return "BackgroundBlurRadiusY";
        case RSModifierType::FOREGROUND_BLUR_RADIUS:
            return "ForegroundBlurRadius";
        case RSModifierType::FOREGROUND_BLUR_SATURATION:
            return "ForegroundBlurSaturation";
        case RSModifierType::FOREGROUND_BLUR_BRIGHTNESS:
            return "ForegroundBlurBrightness";
        case RSModifierType::FOREGROUND_BLUR_MASK_COLOR:
            return "ForegroundBlurMaskColor";
        case RSModifierType::FOREGROUND_BLUR_COLOR_MODE:
            return "ForegroundBlurColorMode";
        case RSModifierType::FOREGROUND_BLUR_RADIUS_X:
            return "ForegroundBlurRadiusX";
        case RSModifierType::FOREGROUND_BLUR_RADIUS_Y:
            return "ForegroundBlurRadiusY";
        case RSModifierType::CUSTOM:
            return "Custom";
        case RSModifierType::EXTENDED:
            return "Extended";
        case RSModifierType::TRANSITION:
            return "Transition";
        case RSModifierType::BACKGROUND_STYLE:
            return "BackgroundStyle";
        case RSModifierType::CONTENT_STYLE:
            return "ContentStyle";
        case RSModifierType::FOREGROUND_STYLE:
            return "ForegroundStyle";
        case RSModifierType::OVERLAY_STYLE:
            return "OverlayStyle";
        case RSModifierType::NODE_MODIFIER:
            return "NodeModifier";
        case RSModifierType::ENV_FOREGROUND_COLOR:
            return "EnvForegroundColor";
        case RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY:
            return "EnvForegroundColorStrategy";
        case RSModifierType::GEOMETRYTRANS:
            return "Geometrytrans";
        case RSModifierType::CHILDREN:
            return "Children";
        case RSModifierType::MAX_RS_MODIFIER_TYPE:
            return "MaxRsModifierType";
        default:
            return "UNKNOWN";
    }
};

} // namespace Rosen
} // namespace Keels
